package net.lab1024.sa.admin.module.business.ball.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.ball.bo.Lottery3D;
import net.lab1024.sa.admin.module.business.ball.dao.Lottery3DMapper;
import net.lab1024.sa.admin.module.business.ball.service.Lottery3dService;
import net.lab1024.sa.admin.module.business.ball.util.BallUtil;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class Lottery3dServiceImpl  extends ServiceImpl<Lottery3DMapper, Lottery3D> implements Lottery3dService {
    private final String threeDDataurl = "http://data.caiminbang.com/chart/3D/3d_zhfb_year.html";



    @Override
    public void update3D() throws IOException {
        Document doc = Jsoup.connect(StringUtils.replace(threeDDataurl, "year", DateUtil.format(new Date(), "yyyy"))).get();
        List<Lottery3D> ballList = parse3d(doc);
        saveOrUpdateBatch(ballList);
    }

    /**
     * 历史数据同步
     */
    List<Integer> years = Lists.newArrayList(2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023);

    @Override
    public void getAll3dData() {
        years.forEach(y ->{
            String newUrl = StringUtils.replace(threeDDataurl, "year", y.toString());
            Document doc = null;
            try {
                doc = Jsoup.connect(newUrl).get();
                List<Lottery3D> ballList = parse3d(doc);
                saveOrUpdateBatch(ballList);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    private List<Lottery3D> parse3d(Document doc) {
        List<Lottery3D> lottry3dList = Lists.newLinkedList();
        Elements qihaoElements = doc.select("#tpzt > table > #tbZw > tr .qiHao");
        Elements kaijiangElements = doc.select("#tpzt > table > #tbZw > tr .kaiJiang");
        qihaoElements.forEach(qihao ->{
            lottry3dList.add(new Lottery3D(qihao.text(), kaijiangElements.get(qihaoElements.indexOf(qihao)).text()));
        });
        return lottry3dList;
    }

    @Override
    public List<Lottery3D> threeDForecast(Integer limit)  {
        LambdaQueryWrapper<Lottery3D> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Lottery3D::getPhase).last("limit " + limit);
        List<Lottery3D> balls = list(queryWrapper);

        if (balls.isEmpty()) {
            System.out.println("没有数据可供预测");
            return null;
        }
        List<Integer> minB1 = BallUtil.countAndSort(balls.stream().map(Lottery3D::getBall1).collect(Collectors.toList()), 0,9);
        List<Integer> minB2 = BallUtil.countAndSort(balls.stream().map(Lottery3D::getBall2).collect(Collectors.toList()), 0,9);
        List<Integer> minB3 = BallUtil.countAndSort(balls.stream().map(Lottery3D::getBall3).collect(Collectors.toList()), 0,9);

        String msg = "福彩3d获取过去"+limit+"期内各个位置上出现次数最少的数字";
        Lottery3D lottery3D = new Lottery3D().setBall1(minB1.get(0)).setBall2(minB2.get(0)).setBall3(minB3.get(0)).setMsg(msg);
        List<Lottery3D> lottery3DList = Lists.newArrayList(lottery3D);
        return lottery3DList;
    }


    public static List<Integer> getNumbersWithMinFrequency(List<Integer> numbers) {
        Map<Integer, Long> frequencyMap = numbers.stream()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        int minFrequency = frequencyMap.values().stream().mapToInt(Long::intValue).min().orElse(0);
        return frequencyMap.entrySet().stream()
                .filter(entry -> entry.getValue() == minFrequency)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }

}
